/////precompiled////////
#include "precompiled.h"
////////////////////////


#include "frm_control_TString.h"
#include "frm_control_TPara.h"
#include "frm_control_TFrame.h"
#include "svl_TClipboard.h"

using namespace frm;
using namespace control;

// TStyle /////////////////////////////////////////////////////////////////////

//                      
TString::TStyle::TStyle()
{
	Normal .Cursor.Set(cursor::TCursorWin(IDC_IBEAM));
	Focused.Cursor.Set(cursor::TCursorWin(IDC_IBEAM));
	Selected.Cursor.Set(cursor::TCursorWin(IDC_IBEAM));
}

//
void TString::TStyle::SetFontDefault()
{
	Normal.Font.Name  .SetValue("Arial");
	Normal.Font.Height.SetValue(20);
	Normal.Font.Style .SetValue(grf::TFontStyle());
	Normal.Font.Color .SetValue(0,0,0);
	Normal.Font.CalcAll();
	 
	Focused.Font.Name  .SetValue("Arial");
	Focused.Font.Height.SetValue(20);
	Focused.Font.Style .SetValue(grf::TFontStyle());
	Focused.Font.Color. SetValue(255,0,0);
	Focused.Font.CalcAll();
	
	Selected.Font.Name  .SetValue("Arial");
	Selected.Font.Height.SetValue(20);
	Selected.Font.Style .SetValue(grf::TFontStyle());
	Selected.Font.Color. SetValue(0,0,255);
	Selected.Font.CalcAll();
}

//
void TString::TStyle::CalcFontAll()
{
	Normal .Font.CalcAll();
	Focused.Font.CalcAll();
	Selected.Font.CalcAll();
}

//
void TString::TStyle::SetFontParent(TStyle &Parent)
{
	Normal .Font.SetParent(Parent.Normal .Font); //Parent.Normal .Font.CalcAll();
	Focused.Font.SetParent(Parent.Focused.Font); //Parent.Focused.Font.CalcAll();
	Selected.Font.SetParent(Parent.Selected.Font); //Parent.Focused.Font.CalcAll();
}

//
void TString::TStyle::SetFromParent(frm::TStyle *Parent_)
{
	if (!Parent_) {
		SetFontParent(GetDefault());
		return;
	}

	TStyle *Parent = dynamic_cast<TStyle*>(Parent_);
	
	Normal.Font  .SetParent    (Parent->Normal.Font);
	Normal.Filler.SetFromParent(Parent->Normal.Filler);
	Normal.Cursor.SetFromParent(Parent->Normal.Cursor);
	Normal.Border.SetFromParent(Parent->Normal.Border);

	Focused.Font  .SetParent    (Parent->Focused.Font);
	Focused.Filler.SetFromParent(Parent->Focused.Filler);
	Focused.Cursor.SetFromParent(Parent->Focused.Cursor);
	Focused.Border.SetFromParent(Parent->Focused.Border);
	
	Selected.Font  .SetParent    (Parent->Selected.Font);
	Selected.Filler.SetFromParent(Parent->Selected.Filler);
	Selected.Cursor.SetFromParent(Parent->Selected.Cursor);
	Selected.Border.SetFromParent(Parent->Selected.Border);
}

//
svl::TInfoParam TString::TStyle::TState::AddInfoTo(svl::TInfoParam Info)
{
	return TPanel::TStyle::AddInfoTo(Info)
	 .Add("Font",Font);
}

//
svl::TInfoParam TString::TStyle::AddInfoTo(svl::TInfoParam Info)
{
	return frm::TStyle::AddInfoTo(Info)
	 .Add("Normal", Normal)
	 .Add("Focused",Focused)
	 .Add("Selected",Selected)
	;
/******
	svl::TInfo &Info = frm::TStyle::AddInfoTo(Info_,S);
	Normal.AddInfoTo(Info,"Normal");
	Focused.AddInfoTo(Info,"Focused");
	return Info;
*******/  
}

//
TString::TStyle &TString::TStyle::GetDefault()
{
	struct TStyle : public TString::TStyle
	{
		TStyle() { SetFontDefault(); }
	};
	static TStyle Style; return Style;
}

// TString ////////////////////////////////////////////////////////////////////

//
TString::TString(TWindow &Window) : TPanel(Window)//,Events(*this)
{
	SetStyle(TStyle::GetDefault());
}

//
TString::~TString()
{
/****************
	if (Focus_IsEnter())
	{
		int N =0;
		Focus_Exit();
	}
***************/  
}

//
TString &TString::SetStyle(TStyle &V)
{
	if (style == &V) {
		return *this;
	}
	 
	TBeginPaint BeginPaint(this); 
	InsertPaint(this); 

	style = &V; 
	grf::TClientDC DC(GetWindow());
	
	if (Focus_IsEnter()) { 
		TPanel::SetStyle(style->Focused);
		DC.Select(style->Focused.Font);
	}
	else { 
		TPanel::SetStyle(style->Normal);
		DC.Select(style->Normal.Font);
	}
	
	//ReupdateValue(); 
/****************  
	grf::TClientDC DC(GetWindow());

	if (Focus_IsEnter()) { 
		DC.Select(style->Focused.Font);
	}
	else { 
		DC.Select(style->Normal.Font);
	}
******************/  

	grf::TSize Size = DC.GetTextExtent(value,value.Len());

	if (Size.Width == 0) { 
		Size.Width = 10;
	}
//else                 { Size.Width += 2;}

	GetWOrdinate().UpdateSize(Size.Width); 
	
	if (GetHeight() != Size.Height) {
		::TEXTMETRIC TM; DC.GetTextMetrics(TM);
		GetHOrdinate().GetCalcSize().SetBase(TM.tmAscent);
		GetHOrdinate().UpdateSize(Size.Height);
	}
 
	return *this;
}

//
void TString::SetValueE(svl::TString V/*,TEvents::EChangeValue eChangeValue*/)
{
	svl::TString OldValue = value;
	//Events.BeforeChangeValue(TEvents::TChangeValue(Events,eChangeValue,OldValue,V));
	value = V;

	grf::TClientDC DC(GetWindow());

	if (Focus_IsEnter()) { DC.Select(style->Focused.Font);}
	else                 { DC.Select(style->Normal .Font);}

	grf::TSize Size = DC.GetTextExtent(value,value.Len());

	if (Size.Width == 0) { Size.Width = 10;}
//else                 { Size.Width += 2;}

	SetClientWidth(Size.Width);
	::TEXTMETRIC TM; DC.GetTextMetrics(TM);
	GetHOrdinate().GetCalcSize().SetBase(TM.tmAscent);
	SetClientHeight(Size.Height);

	//Events.AfterChangeValue(TEvents::TChangeValue(Events,eChangeValue,OldValue,V));
}

//
svl::TString TString::GetValue()
{
	return value;
}

//
void TString::UpdateValueE(svl::TString V/*,TEvents::EChangeValue eChangeValue*/)
{
	BeginPaint();
	InsertPaint(this);

	svl::TString OldValue = value;
//  Events.BeforeChangeValue(TEvents::TChangeValue(Events,eChangeValue,OldValue,V));
	value = V; 
	
	grf::TClientDC DC(GetWindow());

	if (Focus_IsEnter()) { DC.Select(style->Focused.Font);}
	else                 { DC.Select(style->Normal .Font);}

	grf::TSize Size = DC.GetTextExtent(value,value.Len());

	if (Size.Width == 0) { Size.Width = 10;}
//else                 { Size.Width += 2;}

	UpdateClientWidth(Size.Width); 
	
	if (GetHeight() != Size.Height) {
		::TEXTMETRIC TM; DC.GetTextMetrics(TM);
		GetHOrdinate().GetCalcSize().SetBase(TM.tmAscent);
		UpdateClientHeight(Size.Height);
	}

//  Events.AfterChangeValue(TEvents::TChangeValue(Events,eChangeValue,OldValue,V));
	EndPaint();
}

//
void TString::ReupdateValue()
{
	TPanelSelect* ps = GetSelectThisOrParent();
	if(ps){
		ps->sel_min = ps->sel_beg < ps->sel_end ? ps->sel_beg : ps->sel_end;
		ps->sel_max = ps->sel_beg > ps->sel_end ? ps->sel_beg : ps->sel_end;
	}
				
	BeginPaint();
	InsertPaint(this);

	grf::TClientDC DC(GetWindow());

	if (Focus_IsEnter()) { DC.Select(style->Focused.Font);}
	else                 { DC.Select(style->Normal .Font);}

	grf::TSize Size = DC.GetTextExtent(value,value.Len());

	if (Size.Width == 0) { Size.Width = 10;}
//else                 { Size.Width += 2;}

	UpdateClientWidth(Size.Width); 
	
	if (GetHeight() != Size.Height)  {
		::TEXTMETRIC TM; DC.GetTextMetrics(TM);
		GetHOrdinate().GetCalcSize().SetBase(TM.tmAscent);
		UpdateClientHeight(Size.Height);
	}

	EndPaint();
}

//
int TString::XSizeToPos(int XSize)
{
	grf::TClientDC DC(GetWindow());

	if (Focus_IsEnter()) { DC.Select(style->Focused.Font);}
	else                 { DC.Select(style->Normal .Font);}

	svl::TString Str = value;
	int       L = Str.Len(),Pos = 0;
	char     *S = Str.S();

	for (Pos = 0; Pos < L; Pos++)
	{
		int Width = DC.GetTextExtent(S, Pos).Width + (DC.GetTextExtent(S + Pos, 1 ).Width / 2);
		if( Width >= XSize) break;
		//grf::TSize Size = DC.GetTextExtent(S,Pos+1);
		//if (Size.Width >= XSize) { break;}
	}
	return min(L,Pos);
}

//
int TString::PosToXSize(int Pos)
{
	grf::TClientDC DC(GetWindow());

	if (Focus_IsEnter()) 
		{ DC.Select(style->Focused.Font);}
	else                     
		{ DC.Select(style->Normal.Font);}

	Pos = min(Pos,value.Len());
	grf::TSize Size = DC.GetTextExtent(value.S(),Pos);
	return Size.Width;
}

//
bool TString::DeleteSymbolInPos(int Pos)
{
	if (Pos < value.Len())
		{ value.DelSym(Pos); return true; }
	return false;
}

//
TComponent *TString::TComponent_New()
{
	return new TString(GetWindow());
}

//
void TString::TComponent_Paint(TPaint &Paint,int NPaintStack)
{
	TPanel::TComponent_Paint(Paint,NPaintStack);
		
	if (Focus_IsEnter())
	{
		style->Focused.Font.Paint(*this,Paint,value);
		TComponent_SetCaretByPos(Paint.GRect,Focus_GetPos());
	}
	else { style->Normal.Font.Paint(*this,Paint,value); }
}

//
void TString::TComponent_Mouse(TMouse Mouse)
{
	TPanelSelect* ps = GetSelectThisOrParent();
	
	switch (Mouse.State)
	{
		case grf::TMouse::EState_LButtonDown: if (TComponent_FocusEnable())
		{
			TGeometryRect GRect; 
			Mouse_SetCapture(); 
				
			if (!GetWindow().CalcGeometryRect(this,GRect)) {
				Except("TComponent_Mouse");
			}

			int XSize = Mouse.PtClient.X - GRect.RThis.Left;
			int Pos   = XSizeToPos(XSize);

			//Node.Form.Focus.SetByPos(this,GRect,Pos);
			//Node.Form.Focus.FixCaretX();

				if( ps && !(ps->selecting || ps->select) ){
						ps->sel_beg = Focus_GetPos();
				}
				if (Focus_EnterByPos(Pos)) { 
						Focus_FixCaretX(); 

						if (ps) {
							short aaa = ::GetKeyState(VK_SHIFT);
							if( aaa < 0 ) {
								ps->sel_end = Pos;
								ps->select = true;
							}
							else{
								ps->select = true;
								ps->sel_beg = Pos;
								ps->sel_end = Pos;
							}
							ReupdateSelecting();
						}
			}
			return;
		}
		
		case grf::TMouse::EState_LButtonUp: if (TComponent_FocusEnable())
		{
			TGeometryRect GRect; 
			Mouse_ReleaseCapture();
						
			if (!GetWindow().CalcGeometryRect(this,GRect)) {
				Except("TComponent_Mouse");
			}

			int XSize = Mouse.PtClient.X - GRect.RThis.Left;
			int Pos   = XSizeToPos(XSize);

				if( Focus_EnterByPos(Pos) ){
				Focus_FixCaretX(); 
				if( ps && ps->select ){
					ps->sel_end = Pos;
					ReupdateSelecting();
					ps->select = false;
					if( ps->sel_beg != ps->sel_end )
						ps->selecting = true;
				}
			}
			return;
		}
		
		case grf::TMouse::EState_Move: if (TComponent_FocusEnable())
		{
			if (!ps) {
				return;
			}
			TGeometryRect GRect; 
			
			if (!GetWindow().CalcGeometryRect(this,GRect)) {
				Except("TComponent_Mouse");
			}

			int XSize = Mouse.PtClient.X - GRect.RThis.Left;
			int Pos   = XSizeToPos(XSize);

			if( ps && ps->select ){
				ps->sel_end = Pos;
				ps->selecting = true;
				ReupdateSelecting();
			}
			return;
		}

	}
	TPanel::TComponent_Mouse(Mouse);
}                    

void TString::ReupdateSelecting(){
	TPanelSelect* ps = GetSelectThisOrParent();
	ps->sel_min = ps->sel_beg < ps->sel_end ? ps->sel_beg : ps->sel_end;
	ps->sel_max = ps->sel_beg > ps->sel_end ? ps->sel_beg : ps->sel_end;
	
	TBeginPaint bp(this);
	InsertPaint(this);
}

void TString::UpdateSelected(int oldPos,grf::TKeyboardKey &KeyboardKey){
	int Pos = Focus_GetPos();
	
	TPanelSelect* ps = GetSelectThisOrParent();

	if (!ps) {
		return;
	}
	
	if( KeyboardKey.Shift.Contains( grf::TShift::Shift ) ){
		if( ps->selecting ){
			ps->sel_end = Pos;
		}
		else{
			ps->selecting = true;
			ps->sel_beg = oldPos;
			ps->sel_end = Pos;
		}
	}
	else{
		ps->selecting = false;
		ps->select = false;
	}

	ReupdateValue();
}



//
void TString::TComponent_KeyboardKey(grf::TKeyboardKey &KeyboardKey) {
	int Pos = Focus_GetPos();

	TPanelSelect* ps = GetSelectThisOrParent();
	
	if (KeyboardKey.State == grf::TKeyboardKey::EState_Down) {
		
		if( KeyboardKey.Key == VK_INSERT ){
			if( KeyboardKey.Shift.Contains( grf::TShift::Ctrl ) ){
				Copy();
				return;
			}
			if( KeyboardKey.Shift.Contains( grf::TShift::Shift ) ){
				Paste();
				return;
			}
		}
		if( KeyboardKey.Key == VK_DELETE ){
			if( KeyboardKey.Shift.Contains( grf::TShift::Shift ) ){
				Cut();
				return;
			}
		}
		if (KeyboardKey.Key == VK_LEFT && Pos > 0) {
			if (Focus_EnterByPos(Pos-1)) { 
				UpdateSelected(Pos,KeyboardKey);
				Focus_FixCaretX(); 
			}
			return;
		}
		else if (KeyboardKey.Key == VK_HOME && Pos > 0) {
			if (Focus_EnterByPos(0)) { 
				UpdateSelected(Pos,KeyboardKey);
				Focus_FixCaretX(); 
			}
			return;
		}
		else if (KeyboardKey.Key == VK_RIGHT && Pos < value.Len()) {
			if (Focus_EnterByPos(Pos+1)) { 
				UpdateSelected(Pos,KeyboardKey);
				Focus_FixCaretX(); 
			}
			return;
		}
		else if (KeyboardKey.Key == VK_END && Pos < value.Len()) {
			if (Focus_EnterByPos(value.Len())) { 
				UpdateSelected(Pos,KeyboardKey);
				Focus_FixCaretX(); 
			}
			return;
		}
		else if (/*KeyboardKey.Shift.IsEmpty() &&*/ KeyboardKey.Key == VK_DELETE ) {
			if( EraseSelectionText() )
				return;
			if( Pos < value.Len() ){
				TBeginPaint BP(this);
				svl::TString Sym,SEdit = value; 
				SEdit.DelSubStr(Pos,1,Sym);
				UpdateValue(SEdit);
				return;
			}
		}
		else if (KeyboardKey.Key == VK_BACK ) {
			if( EraseSelectionText() )
				return;
			if( Pos > 0 ){
				TBeginPaint BP(this);
				svl::TString Sym,SEdit = value; 
				SEdit.DelSubStr(Pos-1,1,Sym);
			
				if (UpdateValue(SEdit)) { 
					if (Focus_EnterByPos(Pos-1)) { 
						Focus_FixCaretX(); 
					} 
				}
				return;
			}
		}
	}
	TPanel::TComponent_KeyboardKey(KeyboardKey);
}

//
void TString::TComponent_KeyboardChar(grf::TKeyboardChar &KeyboardChar)
{
	switch (KeyboardChar.Key)
	{
		case VK_BACK: case VK_RETURN: case VK_ESCAPE: break;
		case 3:{ // ctrl + c
			Copy();
			break;
		}
		case 22:{ // ctrl + v
			Paste();
			break;
		}
		case 24:{ // ctrl + x
			Cut();
			break;
		}
		/** case 'c':case 'v':{
			short ks = ::GetKeyState( VK_CONTROL );
			if( ks < 0 ){//if( KeyboardKey.Shift.Contains( grf::TShift::Ctrl ) ){
				if(KeyboardChar.Key ==  'c'){
					svl::TString str;
					GetSelectionText( str );
					svl::TClipboard::Add( str );
					break;
				}else{
					svl::TString str;
					svl::TClipboard::Get( str );
					InsertInCaretPos( str );
					break;
				}}} /**/
		default: {
			EraseSelectionText();
				
			svl::TString SEdit = value;
			int Pos = Focus_GetPos();
			SEdit.InsSym(Pos,KeyboardChar.Key);

			TBeginPaint BP(this);
			if (UpdateValue(SEdit)) { 
				if (Focus_EnterByPos(Focus_GetPos()+1)) { 
					Focus_FixCaretX(); 
				} 
			}
		}
	}
	TPanel::TComponent_KeyboardChar(KeyboardChar);
}

//
TComponent *TString::TComponent_SplitInSize(TMergeSplit &MS,int InSize)
{
	//InSize -= GetWOrdinate().GetBorder().GetSize();

	grf::TClientDC DC(GetWindow());

	if (Focus_IsEnter()) { 
		DC.Select(style->Focused.Font);
	}
	else { 
		DC.Select(style->Normal.Font);
	}

	svl::TString Str = value;
	int   L = Str.Len();
	char *S = Str.S();

	for (int N = 0; N < L; N++) if (DC.GetTextExtent(S,N+1).Width > InSize) {
		if (N == 0) { 
			return NULL;
		}

		if (S[N] != ' ') for (int Nb = N; Nb > 0; Nb--) {
			if (S[Nb] == ' ') { 
				N = Nb+1; 
				break; 
			}
		}

		svl::TString Sf,Sl; value.SplitTo(N,Sf,Sl);
		SetValue(Sf);

		TString *CNew = dynamic_cast<TString*>(TComponent_New());

		CNew->SetStyle(*style);
		CNew->SetValue(Sl);

		if (MS.Focus == this && Sf.Len() < MS.Pos) { 
			MS.Focus = CNew; 
			MS.Pos  -= Sf.Len(); 
		}
		return CNew;
	}
	return NULL;
}

//
TComponent *TString::TComponent_SplitInPos(TMergeSplit &MS,int InPos)
{
	svl::TString Sf,Sl; 
	
	if (InPos < value.Len()) { 
		value.SplitTo(InPos,Sf,Sl); 
		SetValue(Sf); 
	}
	else { 
		Sf = value; 
	}

	TString *NewString = dynamic_cast<TString*>(TComponent_New());

	NewString->SetStyle(*style);
	NewString->SetValue(Sl);

	if (MS.Focus == this && Sf.Len() < MS.Pos+1) { 
		MS.Focus = NewString; 
		MS.Pos -= Sf.Len(); 
	}
	return NewString;
}

//
bool TString::TComponent_MergeFrom(TMergeSplit &MS,TComponent *InCFrom)
{
	TString *CFrom = dynamic_cast<TString*>(InCFrom);

	if (CFrom && style == CFrom->style) {
		if (MS.Focus == CFrom) {
			MS.Focus = this; 
			MS.Pos += GetValue().Len();
		}
		SetValue(GetValue() << CFrom->GetValue());
		return true;
	}
	return false;
}

//
void TString::TComponent_FocusEnter()
{
	TPanel::TComponent_FocusEnter();

	TPanelSelect *Select = GetSelectThisOrParent();

	if (Select) { 
		Select->SetEnter(this);
	}
	
	TPanel::SetStyle(style->Focused);
	ReupdateValue();
}

//
void TString::TComponent_FocusExit()
{
	TPanel::TComponent_FocusExit();

	TPanelSelect *Select = GetSelectThisOrParent();

	if (Select && Select->IsEntered(this)) { 
		TPanel::UpdateStyle(style->Selected);
	}
	else { 
		TPanel::UpdateStyle(style->Normal);
	}

}

//
void TString::TComponent_SelectEnter()
{
	TPanel::TComponent_SelectEnter();

	if (!Focus_IsEnter()) { 
		TPanel::UpdateStyle(style->Selected);
	}
}

//
void TString::TComponent_SelectExit()
{
	TPanel::TComponent_SelectExit();
	TPanel::UpdateStyle(style->Normal);
}









//
bool TString::TComponent_CaretIsBegin()
{
	return Focus_GetPos() == 0;
}

//
bool TString::TComponent_CaretIsEnd()
{
	return Focus_GetPos() == value.Len();
}

//
void TString::TComponent_SetCaretToBegin()
{
	Focus_EnterByPos(0);
}

//
void TString::TComponent_SetCaretToEnd()
{
	Focus_EnterByPos(value.Len());
}

//
int TString::TComponent_GetCaretMaxPos()
{
	return value.Len();
}

//
void TString::TComponent_SetCaretByX(TGeometryRect &GRect,int XClient)
{
	grf::TCaret   &Caret = GetFocus().Caret;
	grf::TClientDC DC(GetWindow());

	DC.Select(style->Focused.Font);

	svl::TString Str = value;
	int   W = 0,L = Str.Len(),Pos = 0;
	char *S = Str.S();

	int InX = XClient - GRect.RThis.Left;

	for (Pos = 0; Pos < L; Pos++)
	{
		grf::TSize Size = DC.GetTextExtent(S,Pos+1);
		if (Size.Width >= InX) { break;}
		W = Size.Width;
	}
	int X = GRect.RThis.Left + W;
	int Y = GRect.RThisVisible.Top;

	Caret.RClient = grf::TRect(X,Y, 2,GRect.RThisVisible.Height);
	Caret.Hide();
	Caret.Update();              
	Caret.Show();

	Focus_SetPos(Pos);
}

//
void TString::TComponent_SetCaretByPos(TGeometryRect &GRect,int Pos)
{
/**********
if (!Focus_IsEnter())
{
::MessageBeep(0);
}  
***********/

	grf::TCaret &Caret = GetFocus().Caret;

	grf::TClientDC DC(GetWindow());
	DC.Select(style->Focused.Font);

	Pos = min(Pos,value.Len());
	grf::TSize Size = DC.GetTextExtent(value,Pos);

	int X = GRect.RThis.Left + Size.Width;
	int Y = GRect.RThisVisible.Top;

	if (GRect.RThisVisible.IsContainX(X))
	{
		Caret.RClient = grf::TRect(X,Y, 2,GRect.RThisVisible.Height);
		Caret.Hide();
		Caret.Update();
		Caret.Show();
	}
	else { Caret.Destroy();}

	Focus_SetPos(Pos);
}

//
void TString::TComponent_ScrollToVisible(TGeometryRect &GRect)
{
	TFrame *CurrFrame = dynamic_cast<TFrame*>(SearchThisOrParent(TFrame::TType())); if (CurrFrame)
	{
		grf::TClientDC DC(GetWindow());
		DC.Select(style->Focused.Font);

		int Pos = min(Focus_GetPos(),value.Len());
		grf::TSize Size = DC.GetTextExtent(value,Pos);

		grf::TRect R;
			R.Left = GRect.RThis.Left + (Size.Width - 20);
			//R.Left = Node.Form.Focus.GetX();
			R.Top  = GRect.RThis.Top;
			R.Width = 40;
			R.Height = Size.Height;

		CurrFrame->ScrollToVisibleRect(*this,R);
	}
}

//
void TString::TComponent_AfterChangeWidth(int OldVal,int NewVal)
{
	TPanel::TComponent_AfterChangeWidth(OldVal,NewVal);

	TLine *Line = dynamic_cast<TLine*>(GetParent()); if (!Line)
		{ return; }
	TPara *Para = dynamic_cast<TPara*>(Line->GetParent()); if (!Para)
		{ return; }
	Para->Child_AfterChangeWidth(OldVal,NewVal);
}

//
void TString::TComponent_ChangeScale(double Scale) 
{
	style->Normal .Font.ToScale(Scale);
	style->Focused.Font.ToScale(Scale);

	grf::TClientDC DC(GetWindow());

	if (Focus_IsEnter()) { DC.Select(style->Focused.Font);}
	else                 { DC.Select(style->Normal .Font);}

	grf::TSize Size = DC.GetTextExtent(value,value.Len());

	if (Size.Width == 0) { Size.Width = 10;}
//else                 { Size.Width += 2;}

	GetWOrdinate().UpdateSize(Size.Width); if (GetHeight() != Size.Height)
	{
		::TEXTMETRIC TM; DC.GetTextMetrics(TM);
		GetHOrdinate().GetCalcSize().SetBase(TM.tmAscent);
		GetHOrdinate().UpdateSize(Size.Height);
	}
}

//
void TString::TComponent_InheritStyleFrom(TTableOfStyles &ParentStyles)
{ 
	TStyle *Style = dynamic_cast<TStyle*>(ParentStyles.SearchByEqualType(TStyle::TType())); if (Style) {
		SetStyle(*Style);
	}
}




	
/************************************************
//  style = default
//    values
//      default
//        cursor = cursorWin(IDC_ARROW)
//        bkFiller = fillerColor(grf::TColor(255,255,255))
//        font
//          name = "Arial"
//          height = 20
//          color = grf::TColor(0,0,0)
//
//      para
//        normal
//          cursor = cursorWin(IDC_IBEAM)
//
//      string
//        normal
//          cursor = cursorWin(IDC_IBEAM)
//          filler = fillerColor(grf::TColor(255,255,255))
//          font
//            name = "Arial"
//            height = 20
//            color = grf::TColor(0,0,0)
//        focused
//          filler = fillerColor(grf::TColor(0,0,255))
//          font
//            color = grf::TColor(255,255,255)
//
//      button
//        normal
//          cursor = cursorWin(IDC_UPARROW)
//          filler = TButtonN
//        down
//          filler = TButtonD
//
//      splitter
//        vert
//          normal
//            cursor = cursorWin(1)
//            frFiller = TButtonN
//          down
//            frFiller = TButtonD
//        horz
//          normal
//            cursor = cursorWin(2)
//            frFiller = TButtonN
//          down
//            frFiller = TButtonD
//        both
//          normal
//            cursor = cursorWin(3)
//            frFiller = TButtonN
//          down
//            frFiller = TButtonD


//        default
//          normal
//            cursor = cursorWin(0)
//            filler = TButtonN
//          down
//            filler = TButtonD
//        vert
//          normal
//            cursor = cursorWin(1)
//        horz
//          normal
//            cursor = cursorWin(1)
//        both
//          normal
//            cursor = cursorWin(1)


//        default
//          cursor = cursorWin(IDC_UPARROW)
//          filler = TButtonN
//        normal
//          cursor = cursorWin(IDC_UPARROW)
//          filler = TButtonN
//          vert
//            cursor = cursorWin(1)
//          horz
//            cursor = cursorWin(2)
//          both
//            cursor = cursorWin(3)
//        down
//          filler = TButtonD
//
//
//
//
//
//
//    children
//      style = a
//        values
//
//
//
//
//
//
//
//

//stringDef
//  normal
//    cursor = cursorWin(IDC_IBEAM)
//    filler = fillerColor(grf::TColor(255,255,255))
//    font
//      name = "Arial"
//      height = 20
//      color = grf::TColor(0,0,0)
//  focused
//    filler = fillerColor(grf::TColor(0,0,255))
//    font
//      color = grf::TColor(255,255,255)

//string1
//  normal
//    font
//      height = 30
//      style = bold,italic
***************************************************/

void TString::GetSelectionText( svl::TString &str ){
	frm::control::TPanelSelect *ps = GetSelectThisOrParent();
	str.Clear();
	if( ps && (ps->select || ps->selecting) )
		str.Add( value.S() + ps->sel_min, ps->sel_max - ps->sel_min );
}

bool TString::EraseSelectionText(){
	frm::control::TPanelSelect *ps = GetSelectThisOrParent();
	if( ps && (ps->select || ps->selecting) ){
		svl::TString str;
		value.DelSubStr( ps->sel_min, ps->sel_max-ps->sel_min, str );
		ps->select = ps->selecting = false;
		Focus_EnterByPos( ps->sel_min );
		Focus_FixCaretX();
		ReupdateValue();
		return true;
	}
	return false;
}

void TString::InsertInCaretPos( svl::TString &str ){
	value.InsSubStr( Focus_GetPos(), str );
	Focus_EnterByPos( Focus_GetPos() + str.Len() );
	Focus_FixCaretX();
	frm::control::TPanelSelect *ps = GetSelectThisOrParent();
	if( ps  )
		ps->select = ps->selecting = false;
	ReupdateValue();
}

void TString::Copy(){
	svl::TString str;
	GetSelectionText( str );
	svl::TClipboard::Add( str );
}

void TString::Paste(){
	svl::TString str;
	svl::TClipboard::Get( str );
	InsertInCaretPos( str );
}

void TString::Cut(){
	svl::TString str;
	GetSelectionText( str );
	svl::TClipboard::Add( str );
	EraseSelectionText();
}
